package ar.edu.uba.fi.jmit.aspecter;

import java.lang.reflect.InvocationTargetException;

import javassist.ClassPool;
import javassist.CtClass;
import ar.edu.uba.fi.jmit.aspecter.core.interceptor.Interceptor;
import ar.edu.uba.fi.jmit.aspecter.testUtils.ExceptionAfterNewInstanceInterceptor;

public class NewInstanceAccessInterceptorTestCase extends AspecterTestCase {
	
	public void testNewExprAccessInterceptor(){
		try {
			Interceptor interceptor = new ExceptionAfterNewInstanceInterceptor("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest1");
			CtClass ctClass = ClassPool.getDefault().getAndRename("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest9", getNextClassName());
			ctClass.instrument(interceptor);
			Class<?> clazz = ctClass.toClass();
			Object point = clazz.newInstance();
			try{
				clazz.getMethod("instanciatePoint1").invoke(point);
				fail("Exception should be thrown!");
			}catch(InvocationTargetException e) {
				assertEquals("intercepted!", e.getCause().getMessage());
			}
			
		} catch (Exception e) {
			fail(e);
		}
	}
	
	public void testMultipleNewInstanceInterceptors(){
		try {
			Interceptor interceptor1 = new ExceptionAfterNewInstanceInterceptor("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest1");
			Interceptor interceptor2 = new ExceptionAfterNewInstanceInterceptor("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest5");
			Interceptor interceptor3 = new ExceptionAfterNewInstanceInterceptor("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest6");
			Interceptor interceptor4 = new ExceptionAfterNewInstanceInterceptor("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest7");
			
			CtClass ctClass = ClassPool.getDefault().getAndRename("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest9", getNextClassName());
			ctClass.instrument(interceptor1);
			ctClass.instrument(interceptor2);
			ctClass.instrument(interceptor3);
			ctClass.instrument(interceptor4);
			
			Class<?> clazz = ctClass.toClass();
			Object point = clazz.newInstance();
			
			for(int i = 1; i<=4;i++) {
				try{
					clazz.getMethod("instanciatePoint" + i).invoke(point);
					fail("Exception should be thrown!");
				}catch(InvocationTargetException e) {
					assertEquals("intercepted!", e.getCause().getMessage());
				}
			}
			
		} catch (Exception e) {
			fail(e);
		}
	}
	
	public void testMultipleNewInstanceInterceptors2(){
		try {
			Interceptor interceptor1 = new ExceptionAfterNewInstanceInterceptor("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest1");
			
			CtClass ctClass = ClassPool.getDefault().getAndRename("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest9", getNextClassName());
			ctClass.instrument(interceptor1);
			
			Class<?> clazz = ctClass.toClass();
			Object point = clazz.newInstance();
			
			try{
				clazz.getMethod("instanciatePoint1").invoke(point);
				fail("Exception should be thrown!");
			}catch(InvocationTargetException e) {
				assertEquals("intercepted!", e.getCause().getMessage());
			}
			
			for(int i = 2; i<=4;i++) {
				clazz.getMethod("instanciatePoint" + i).invoke(point);
			}
			
			try{
				clazz.getMethod("instanciateAll").invoke(point);
				fail("Exception should be thrown!");
			}catch(InvocationTargetException e) {
				assertEquals("intercepted!", e.getCause().getMessage());
			}
			
		} catch (Exception e) {
			fail(e);
		}
	}

}

